import ctypes
import threading
import time
import os
import gym_pih.hardware.tisgrabber as tis
import cv2
import numpy as np

current_path = os.path.normpath(os.path.dirname(os.path.abspath(__file__)))

class Camera():
    def __init__(self,resoultion="1280x720"):
        """
        Initializes the Imagingsource_for_windows class.

        Args:
            resolution (str): The resolution of the video format. Default is "1280x720". Options are such as "640x480", "1280x720", "1920x1080".

        """
        self.ic = ctypes.cdll.LoadLibrary(current_path+"/tisgrabber_x64.dll")
        tis.declareFunctions(self.ic)
        self.ic.IC_InitLibrary(0)
        self.hGrabber = tis.openDevice(self.ic)
        self.Width = ctypes.c_long()
        self.Height = ctypes.c_long()
        self.BitsPerPixel = ctypes.c_int()
        self.colorformat = ctypes.c_int()
        self.ic.IC_SetVideoFormat(self.hGrabber, tis.T(f"RGB32 ({resoultion})"))
        self.ic.IC_SetFrameRate(self.hGrabber, ctypes.c_float( 60.0))

        self.latest_image = None

    def Open(self):
        if (self.ic.IC_IsDevValid(self.hGrabber)):
            self.ic.IC_StartLive(self.hGrabber, 0)
        else:
            print("can not open camera")
            exit(1)

        self.running = True
        self.thread = threading.Thread(target=self._update_image)
        self.lock = threading.Lock()
        self.thread.start()

    def Close(self):
        self.running = False
        self.ic.IC_StopLive(self.hGrabber)

    def _update_image(self):
        while self.running:
            if self.ic.IC_SnapImage(self.hGrabber, 2000) == tis.IC_SUCCESS:
                # Query the values of image description
                self.ic.IC_GetImageDescription(self.hGrabber, self.Width, self.Height,
                                        self.BitsPerPixel, self.colorformat)
                # Calculate the buffer size
                bpp = int(self.BitsPerPixel.value / 8.0)
                buffer_size = self.Width.value * self.Height.value * self.BitsPerPixel.value
                # Get the image data
                imagePtr = self.ic.IC_GetImagePtr(self.hGrabber)
                imagedata = ctypes.cast(imagePtr,
                                        ctypes.POINTER(ctypes.c_ubyte *
                                                    buffer_size))
                # Create the numpy array
                image = np.ndarray(buffer=imagedata.contents,
                                dtype=np.uint8,
                                shape=(self.Height.value,
                                        self.Width.value,
                                        bpp))
                
                
                # 将图像旋转180度
                rotated_image = cv2.rotate(image, cv2.ROTATE_180)

                # 对旋转后的图像进行水平镜像
                image = cv2.flip(rotated_image, 1)  # 水平翻转，参数为 1

                with self.lock:
                    self.latest_image = image


    def SetProperty(self,propertyname,type,value):
        '''

        Args:
            propertyname: 设置的属性字符串
            type:"Auto" or "Value"
            value:如果是value，则传入数字

        Returns:

        '''
        if(type=="Auto"):
            exposureauto = ctypes.c_long()
            self.ic.IC_SetPropertySwitch(self.hGrabber, tis.T(propertyname), tis.T("Auto"), 1)
        if(type=="Value"):
            self.ic.IC_SetPropertySwitch(self.hGrabber, tis.T(propertyname), tis.T("Auto"), 0)
            self.ic.IC_SetPropertyAbsoluteValue(self.hGrabber, tis.T(propertyname), tis.T("Value"),
                                           ctypes.c_float(value))

    def GetProerty(self,propertyname):
        gain = ctypes.c_long()
        self.ic.IC_GetPropertyValue(self.hGrabber, tis.T(propertyname), tis.T("Value"), gain)
        return gain
    
    def GetImage(self):
        with self.lock:
            return (True, self.latest_image.copy()) if self.latest_image is not None else (False, None)